﻿// 文件路径: Core/NavRoomService.cs
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using RevitProject.Helper;
using RevitProject.SpaceManager.Helper;
using RevitProject.SpaceManager.Models; // 使用 NavRoomModel.cs 中的类
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Application = Autodesk.Revit.ApplicationServices.Application;

namespace RevitProject.SpaceManager.Core
{
    /// <summary>
    /// 提供新房间视图 (NavRoom) 相关的数据访问和业务逻辑。
    /// </summary>
    public class NavRoomService
    {
        private readonly Document _doc;
        private readonly Application _app;
        private readonly UIApplication _uiApp;
        private readonly string _zoneParameterName = "分区"; // !!! 需要您确认实际的分区参数名称 !!!

        /// <summary>
        /// 初始化 NavRoomService。
        /// </summary>
        /// <param name="uiApp">Revit UI 应用程序实例。</param>
        public NavRoomService(UIApplication uiApp)
        {
            _uiApp = uiApp ?? throw new ArgumentNullException(nameof(uiApp));
            _doc = uiApp.ActiveUIDocument.Document;
            _app = uiApp.Application;
        }

        /// <summary>
        /// 获取项目中所有有效的楼层信息。
        /// </summary>
        /// <returns>包含楼层信息的模型列表。</returns>
        public List<LevelInfoModel> GetLevels()
        {
            // (代码同之前的 RoomService.GetLevels)
            try
            {
                return new FilteredElementCollector(_doc)
                    .OfClass(typeof(Level))
                    .Cast<Level>()
                    .Where(l => l != null && l.IsValidObject)
                    .OrderBy(l => l.Elevation)
                    .Select(l => new LevelInfoModel { Id = l.Id, Name = l.Name, Elevation = l.Elevation })
                    .ToList();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"NavRoomService 错误: 获取楼层失败 - {ex.Message}");
                return new List<LevelInfoModel>();
            }
        }

        /// <summary>
        /// 获取所有有效的房间原始数据模型（包括链接模型）。
        /// </summary>
        /// <returns>包含房间数据的模型列表。</returns>
        public List<RoomDataModel> GetAllRoomDataModels()
        {
            // (代码同之前的 RoomService.GetAllRoomDataModels)
            var roomDataModels = new List<RoomDataModel>();
            var rooms = GetAllRevitRooms(_doc); // 获取 Room 元素

            foreach (var room in rooms)
            {
                try
                {
                    roomDataModels.Add(MapRoomToDataModel(room));
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"NavRoomService 错误: 映射房间 {room.Id} 到数据模型失败 - {ex.Message}");
                }
            }
            return roomDataModels;
        }

        /// <summary>
        /// 获取项目中（包括链接）所有有效的 Room 对象。
        /// </summary>
        private List<Room> GetAllRevitRooms(Document currentDoc)
        {
            // (代码同之前的 RoomService.GetAllRevitRooms)
            var rooms = new List<Room>();
            // 当前文档房间
            try
            {
                rooms.AddRange(new FilteredElementCollector(currentDoc)
                    .OfCategory(BuiltInCategory.OST_Rooms)
                    .WhereElementIsNotElementType()
                    .Cast<Room>()
                    .Where(r => r != null && r.Area > 0 && r.Location != null && r.LevelId != ElementId.InvalidElementId));
            }
            catch (Exception ex) { Debug.WriteLine($"NavRoomService 错误获取当前文档房间: {ex.Message}"); }

            // 链接文档房间
            try
            {
                var linkInstances = new FilteredElementCollector(currentDoc).OfClass(typeof(RevitLinkInstance)).Cast<RevitLinkInstance>();
                foreach (var linkInstance in linkInstances)
                {
                    Document linkDoc = null;
                    try { linkDoc = linkInstance.GetLinkDocument(); } catch { continue; } // 忽略未加载的链接
                    if (linkDoc == null) continue;

                    rooms.AddRange(new FilteredElementCollector(linkDoc)
                        .OfCategory(BuiltInCategory.OST_Rooms)
                        .WhereElementIsNotElementType()
                        .Cast<Room>()
                        .Where(r => r != null && r.Area > 0 && r.Location != null && r.LevelId != ElementId.InvalidElementId));
                }
            }
            catch (Exception ex) { Debug.WriteLine($"NavRoomService 错误获取链接文档房间: {ex.Message}"); }

            return rooms;
        }

        /// <summary>
        /// 将 Room 对象映射到 RoomDataModel。
        /// </summary>
        private RoomDataModel MapRoomToDataModel(Room room)
        {
            // (代码同之前的 RoomService.MapRoomToDataModel，但使用 _zoneParameterName)
            if (room == null || !room.IsValidObject) return null;

            var model = new RoomDataModel { Id = room.Id };

            try { model.Name = room.Name ?? "无名称"; } catch { model.Name = "读取错误"; }
            try { model.Number = room.Number ?? "无编号"; } catch { model.Number = "读取错误"; }
            try { model.AreaInternal = room.Area; } catch { model.AreaInternal = 0; }
            try { model.LevelId = room.LevelId; } catch { model.LevelId = ElementId.InvalidElementId; }

            // 预提取楼层信息
            Level level = null;
            if (model.LevelId != ElementId.InvalidElementId)
            {
                try { level = room.Document.GetElement(model.LevelId) as Level; } catch { }
            }
            model.LevelName = level?.Name ?? "未知楼层";
            model.LevelElevationInternal = level?.Elevation ?? 0;

            // 提取分区信息 (使用字段 _zoneParameterName)
            try
            {
                Parameter zoneParam = room.LookupParameter(_zoneParameterName); // 使用字段
                model.ZoneName = zoneParam?.AsString() ?? "无分区";
                if (string.IsNullOrWhiteSpace(model.ZoneName)) model.ZoneName = "无分区";
            }
            catch (Exception ex)
            {
                model.ZoneName = "读取错误";
                Debug.WriteLine($"NavRoomService 映射分区时出错 (Room ID: {room.Id}, Param: {_zoneParameterName}): {ex.Message}");
            }

            // 提取类别信息
            try
            {
                Parameter catParam = room.LookupParameter(SharedParameterHelper.SharedParameterName);
                model.CategoryName = catParam?.AsString() ?? "其他类";
                if (string.IsNullOrWhiteSpace(model.CategoryName)) model.CategoryName = "其他类";
            }
            catch (Exception ex)
            {
                model.CategoryName = "读取错误";
                Debug.WriteLine($"NavRoomService 映射类别时出错 (Room ID: {room.Id}, Param: {SharedParameterHelper.SharedParameterName}): {ex.Message}");
            }

            // 提取其他参数
            try { model.Department = room.LookupParameter("部门")?.AsString() ?? ""; } catch { model.Department = "读取错误"; }
            try { model.Occupancy = room.LookupParameter("占用")?.AsString() ?? ""; } catch { model.Occupancy = "读取错误"; }
            try { model.Comments = room.LookupParameter("注释")?.AsString() ?? ""; } catch { model.Comments = "读取错误"; }
            // 在此添加更多参数读取...

            return model;
        }

        /// <summary>
        /// 获取指定房间列表中存在的所有唯一分区名称。
        /// </summary>
        /// <param name="roomDataModels">房间数据模型列表。</param>
        /// <returns>唯一分区名称列表。</returns>
        public List<string> GetDistinctZones(IEnumerable<RoomDataModel> roomDataModels)
        {
            // (代码同之前的 RoomService.GetDistinctZones)
            if (roomDataModels == null) return new List<string>();
            return roomDataModels
                .Select(r => r.ZoneName)
                .Where(zn => !string.IsNullOrEmpty(zn) && zn != "无分区" && zn != "读取错误")
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .OrderBy(zn => zn)
                .ToList();
        }

        /// <summary>
        /// 获取所有可用的房间分类名称（从现有房间参数中提取唯一值）。
        /// </summary>
        /// <returns>分类名称列表。</returns>
        public List<string> GetAvailableCategories()
        {
            // (代码同之前的 RoomService.GetAvailableCategories)
            var rooms = GetAllRevitRooms(_doc);
            var categories = rooms
                .Select(r => r.LookupParameter(SharedParameterHelper.SharedParameterName)?.AsString())
                .Where(cat => !string.IsNullOrWhiteSpace(cat))
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .OrderBy(cat => cat)
                .ToList();
            // 确保 "其他类" 存在
            if (!categories.Any(c => c.Equals("其他类", StringComparison.OrdinalIgnoreCase)))
            {
                categories.Add("其他类");
                categories.Sort();
            }
            return categories;
        }

        /// <summary>
        /// 在 Revit API 上下文中将指定房间归类到目标类别。
        /// </summary>
        /// <param name="roomIds">要更新的房间 ElementId 列表。</param>
        /// <param name="targetCategoryName">目标分类名称。</param>
        /// <returns>操作成功则返回 true。</returns>
        public async Task<bool> AssignCategoryToRoomsAsync(List<ElementId> roomIds, string targetCategoryName)
        {
            // (代码同之前的 RoomService.AssignCategoryToRoomsAsync)
            if (roomIds == null || !roomIds.Any() || string.IsNullOrEmpty(targetCategoryName))
            {
                Debug.WriteLine("NavRoomService 分配类别: 无效输入。");
                return false;
            }

            var tcs = new TaskCompletionSource<bool>();

            RevitContextHelper.Execute(uiApp =>
            {
                bool success = false;
                Document localDoc = uiApp.ActiveUIDocument.Document;
                ExternalDefinition sharedParamDef = SharedParameterHelper.EnsureParameterExistsAndBound(uiApp.Application, localDoc);
                if (sharedParamDef == null)
                {
                    tcs.TrySetResult(false); // 参数设置失败
                    return;
                }

                using (Transaction tx = new Transaction(localDoc, $"归类房间到 {targetCategoryName}"))
                {
                    try
                    {
                        tx.Start();
                        int updatedCount = 0;
                        foreach (var roomId in roomIds)
                        {
                            Room room = localDoc.GetElement(roomId) as Room;
                            if (room != null)
                            {
                                Parameter param = room.get_Parameter(sharedParamDef);
                                if (param != null && !param.IsReadOnly)
                                {
                                    if (param.AsString() != targetCategoryName) // 仅当值不同时设置
                                    {
                                        if (param.Set(targetCategoryName))
                                        {
                                            updatedCount++;
                                        }
                                    }
                                }
                            }
                        }
                        if (updatedCount > 0)
                        {
                            tx.Commit();
                        }
                        else
                        {
                            tx.RollBack(); // 无更改则回滚
                        }
                        success = true; // 只要没抛异常就算成功
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine($"NavRoomService 分配类别事务错误: {ex.Message}");
                        if (tx.HasStarted() && !tx.HasEnded()) tx.RollBack();
                        success = false;
                        TaskDialog.Show("错误", $"归类房间时出错: {ex.Message}");
                    }
                }
                tcs.TrySetResult(success);
            });

            return await tcs.Task; // 等待 Revit 操作完成
        }
    }
}